﻿#pragma once
#include"Common.hpp"
//简单的定长内存池
template<typename T>
class ObjectPool {
public:
	T* New(){
		T* obj = nullptr;
		if (_freeList) {
			//如果自由链表里面有，则直接取一个来用
			obj = (T*)_freeList;
			_freeList = NextObj(_freeList);
		}
		else {
			if (_remainBytes < sizeof(T)) {
				//如果自由链表没有，而且剩余空间又不足一个，那只能再搞一块大的
				_remainBytes = 1024 * 128;
				_memory = (char*)SystemAlloc(_remainBytes >> 13);
				if (_memory == nullptr) {
					throw std::bad_alloc();//开辟失败就抛异常
				}
			}
			//可以切割一块出来给object了
			obj = (T*)_memory;
			//因为T可能没有指针大，所以我们要确保分配一个超过T大小的空间
			size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
			_memory += objSize;//跳过这段空间
			_remainBytes -= objSize;//剩余空间减少
		}
		//空间分配出去后，还要只用定位new初始化
		assert(obj);
		/*if (!obj) {
			int x = 0;
		}*/
		new(obj)T;
		return obj;
	}
	void Delete(T*obj) {
		obj->~T();//归还之前显示调用一下T的析构函数
		//接着头插到_freeList
		NextObj(obj) = _freeList;//存这个地址
		_freeList = obj;
	}
private:
	char* _memory=nullptr;//指向一个大块内存池 char*是为了方便+
	void* _freeList=nullptr;//管理切好的小块内存（分配和回收）
	size_t _remainBytes=0;//存储内存池的剩余空间
};